////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBot\exceptions.h
///
/// @brief  Defines standard exceptions used across the project
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <stdexcept>


////////////////////////////////////////////////////////////////////////////////////////////////////
/// @class  IllegalMutationException
///
/// @brief  Exception for signaling that a genetic mutation operation was attempted
/// on an object that does not support mutation.
///
/// @author Matthew P. Del Buono
/// @date   12/21/2009
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace CollabRC
{
    namespace Bot 
    {
        namespace AI
        {
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            /// @class  IllegalMutationException
            ///
            /// @brief  Exception that is thrown when an attempt is made to perform a mutation on an object
            /// that does not support mutation
            ///
            /// @author Matthew P. Del Buono
            /// @date   12/24/2009
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            class IllegalMutationException : public std::exception
            {
            public:
                inline IllegalMutationException():exception("Neither this object nor any of its branches support mutation")
                {
                }

                inline IllegalMutationException(const IllegalMutationException &copy):exception(copy) { }

                inline virtual ~IllegalMutationException() { }
            };

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            /// @class  IllegalOperationException
            ///
            /// @brief  Exception for signaling exceptional situations in a computation.
            /// 
            /// Examples of an exceptional operation include division by zero and raising
            /// a negative value to a negative even value.
            ///
            /// @author Matthew P. Del Buono
            /// @date   12/21/2009
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            class IllegalOperationException :
                public std::runtime_error
            {
            public:

                inline IllegalOperationException(const std::string& error):runtime_error(error)
                {
                }

                inline IllegalOperationException(const IllegalOperationException &copy):runtime_error(copy) { }

                inline virtual ~IllegalOperationException(void)
                {
                }
            };

        }

        /**
         * @brief Exception thrown from iterators when an attempt is made
         * to access the current value when there is no such element.
         *
         * Such an exception could occur when an attempt is made to access
         * the current element when the iterator is currently at its
         * "begin" element or "end" element, both of which are just
         * pseudo-elements which are used for management of the iterator
         * and do not contain any actual value.
         * @version $Id$
         * @author Matthew P. Del Buono
         */
        class NoCurrentElementException : public std::runtime_error
        {
        public:
            /** @brief Creates a new NoCurrentElementException with a default error message */
            inline NoCurrentElementException():runtime_error("An attempt was made to access a value beyond the bounds of the iterator") 
            { };

            /** 
             * @brief Creates a new NoCurrentElementException which is a copy of the specified exception 
             * @param copy the exception from which to copy
             */
            inline NoCurrentElementException(const NoCurrentElementException &copy):runtime_error(copy) { };
        };

        /**
         * @brief Exception thrown to signal that an attempt was made to index an
         * array-like structure outside of its bounds.
         * @version $Id$
         * @author Matthew P. Del Buono
         */
        class IndexOutOfRangeException : public std::runtime_error
        {
        public:
            /** @brief Creates a new IndexOutOfRangeException object */
            inline IndexOutOfRangeException():runtime_error("Attempt to access an array-like structure beyond its bounds") { }

            /** 
             * @brief Creates a new IndexOutOfRangeException from the specified
             * exception
             * @param copy the exception from which to make a copy
             */
            inline IndexOutOfRangeException(const IndexOutOfRangeException& copy):runtime_error(copy) { };
        };

    }

    /**
     * @brief Exception that signals when illegal arguments were given
     * to a function.
     *
     * This exception is not meant to be an end-all solution to illegal argument
     * conditions. This exception is intended for situations in which the given
     * illegal arguments indicate a serious code flaw which should be easily
     * detectable if documentation is followed. An example of this would be where
     * a non-optional parameter is skipped. 
     *
     * An example of flawed usage of this
     * exception would be where a call is made whose arguments request division by 
     * zero. This is inappropriate because the code may otherwise be acceptable,
     * and a cascading error could have caused the zero to fall through. Instead,
     * a more detailed exception is appropriate.
     * @version $Id$
     * @author Matthew P. Del Buono
     */
    class IllegalArgumentException : public std::runtime_error
    {
    public:
        /**
         * @brief Creates a new IllegalArgumentException with the specified detail message
         * @param error the detail message regarding the reason the arguments were unacceptable
         */
        inline IllegalArgumentException(const std::string& error):runtime_error(error) { };

        /**
         * @brief Creates a duplicate IllegalArgumentException with the same detail message
         * @param copy the IllegalArgumentException from which to make a copy
         */
        inline IllegalArgumentException(const IllegalArgumentException& copy):runtime_error(copy) { };
    };
}
